Each command in this section is marked as either CommandSequence (CS) or MeshDataEdit (MD). Due to the nature of these two different types of operations, it is illegal to execute a CommandSequence operation during a MeshDataEdit operation (initiated by editbegin() and terminated by editend()). LScript will detect any attempts to perform these illegal operations and terminate the script. Commands that are independent of this constraint are marked as Independent (IN). Included in the state designator will also be the version of LScript in which the command or feature was introduced.
Unless the autoerror pragma has been declared, except where otherwise noted, all LScript Modeler-specific commands return a status value. This status value represents the result returned by the command. In general, any non-zero value indicates an error of some type.
The new() command accepts an optional boolean parameter
(true
,false
) that indicates whether
the display settings (i.e., where you may have positioned
windows) should be reset as well. If not specified, the default
is true
.
void new(reset) // boolean; reset screenBe careful with this command! You can loose all unsaved work, and it cannot be undone.
void undo(void)
void delete(void)
void cut(void) void copy(void) void paste(void)
status load(string) status save(string)
Usually, you will use these commands to "remember" the layers that the user has actively selected before your LScript starts changing any settings. When you are done, you should politely restore the users original layer settings by passing these values to the lyrsetfg() (or lyrsetbg() if the array contains active background information).
The prototypes for these functions are as follows:
result // integer[]; one or // more layer values lyrfg(void) result // integer[]; one or // more layer values lyrbg(void)
These functions will return a layer value, regardless of whether the layer is active foreground, active background, or entirely unselected. The prototypes for these functions are as follows:
result // integer[]; one or // more layer values lyrdata(void) result // integer[]; one or // more layer values lyrempty(void)
result // integer[]; one or // more layer values lyremptyfg(void) result // integer[]; one or // more layer values lyremptybg(void)
This command is identical to the single-quote key (') used in Modeler to swap layers.
void lyrswap(void)
The prototypes for these functions are as follows:
void lyrsetfg(lyr1 // integer; layer number [,lyr2...lyr10]) // additional layers void lyrsetbg(layers) // integer[]; elements are // layers numbers
fixedflex() sets the operating parameters for these flex functions so that they operate on a fixed range along a specified axis. Easements can be specified using the "i" (ease-in) or "o" (ease-out) flags.
status fixedflex(axis, // constant; X, Y or Z start, // number; start of range // in degrees end // number; end of range // in degrees easement) // string; "i" or "o"
status autoflex(axis, // constant; X, Y or Z polarity, // string; "+" or "-" easement) // string; "i" or "o"
status deformregion(radius // vector or number; radius // of region [,center // vector or number; center // of region [,axis]]) // constant; X, Y or Z
void move(offset) // vector or number; // movement offset // along all three // axes void move(xoffset, // number; offset along X // axis yoffset, // number; offset along Y // axis zoffset); // number; offset along Z // axis
void shear(offset) // vector or number; offset // value to apply to // all axes void shear(xoffset, // number; offset along X // axis yoffset, // number; offset along Y // axis zoffset); // number; offset along Z // axis
void magnet(offset) // vector or number; offset // value to apply to // all axes void magnet(xoffset, // number; offset along X // axis yoffset, // number; offset along Y // axis zoffset); // number; offset along Z // axis
status rotate(angle, // number; amount of // degrees to rotate axis // constant; X, Y or Z [,center]) // vector or number; center // of rotation
status twist(angle, // number; amount of // degrees to twist axis // constant; X, Y or Z [,center]) // vector or number; center // of twist
status vortex(angle, // number; amount of vortex // degrees axis // constant; X, Y or Z [,center]) // vector or number; center // of vortex
For example, to scale an object by one-half along the X and Y axes, while maintaining the current scale along the Z,
scale(<.5,.5,1>);Notice in the example that no optional center vector was specified. This value will default to the origin (i.e., <0,0,0>), and all values will be relative to this point.
status scale(amount // vector or number; // scaling factor [,center]) // vector or number; // relative center of // scale
status taper(amount // vector or number; // tapering factor [,center]) // vector or number; // relative center of // taper
status pole(amount // vector or number; pole // factor [,center]) // vector or number; // relative center of // pole
status bend(angle, // number; bend angle in // degrees direction // number; bend direction // in degrees [,center]) // vector or number; // relative center // around which to // bend
UNIFORM |
distributes points across a uniform range. This is the default |
GAUSSIAN |
distributes the offsets in a bell curve around the starting point |
NORMAL |
shifts the points in and out along the local surface normal |
RADIAL |
shifts points in and out along a line through a central point given by the center parameter |
The prototype for jitter() is
status jitter(radius // number; jitter radius [,type // constant; UNIFORM, // GAUSSIAN, NORMAL, // or RADIAL [,cntr]]) // vector or number; // central point used // by RADIAL
status smooth([iterations // number; number of passes // to use [,strength]]) // number; strength of // smoothing
status quantize(size) // vector or number; // defines 3D grid
status mergepoints([dist]) // number; the minimum // point distance
status makebox(lowcorner, // vector or number; low // boundary point highcorner // vector or number; // high boundary point [,nsegments]) // vector or number; count // of box segments
status makeball(radius // vector or number; radius // of sphere nsides // integer; number of // sphere sides nsegments // integer; number of // sphere segments [,center]) // vector or number; center // of sphere
status maketesball(radius // vector or number; radius // of sphere level // integer; level of // tessellation [,center]) // vector or number; center // of sphere
makecone() accepts that same parameters as makedisc(). However, makecone() will cause the top of the cylinder to narrow to a single point.
status makedisc(radius, // vector or number; radius // of disc top, // number; cylinder top // along axis bottom, // number; cylinder bottom // along axis axis, // constant; X, Y or Z nsides // integer; number of side [,nsegments // integer; number of // segments (1) [,center]]) // vector or number; center // of object
The following LScript code snippet illustrates the use of these functions (taken from the logo.ls example script):
findex = fontload(fontName); if(findex != nil) { maketext("LScript",findex);maketext() returns the width (in meters) of the resulting Modeler object.
number maketext(text, // string; text to convert index, // integer; font index from // fontload() [,cornertype // constant; SHARP or // BUFFERED [,spacing // number; spacing between // characters [,scale // number; character // scaling factor [,axis // constant; X, Y or Z [,pos]]]]) // vector or number; // position of first // character
status lathe(axis // constant; X, Y or Z nsides // integer; number of sides // for new object [,center // vector or number; center // about which to // lathe [, end // number; ending angle in // degrees [, start]]]) // number; starting // angle in degrees
status extrude(axis, // constant; X, Y or Z extent // number; distance to // extend along axis [,nsegments]) // integer; number of // additional segments // (default is 1)
status mirror(axis, // constant; X, Y or Z offset) // number; offset of plane // along axis
You can vary the start and end values to cause your object to clone or extrude only along the portion of the motion path represented by those values. For instance, if a motion path were loaded that required 330 frames to traverse, issuing the command
pathextrude("my.mot",1,200,300);would cause your object to begin its extrusion at the frame-200 position of the motion path and continue on through frame-300 position. The sections of the path where your object would have extruded from frames 1 to 199, and from frames 301 to 330, will be empty.
Cloning an object using pathclone() will create a unique duplicate of your object at each step interval. Electing to extrude your object using pathextrude() will create one single, new object with a new segment at each step interval.
Both commands accept the same parameter counts and types.
status pathextrude(filename, // string; name of motion // path file [,step // number; count of // objects/segments to // create [,start // number; starting count [,end]]]) // number; ending count
status railextrude(segments // number; segment count // (0=compute) [,div // constant; KNOTS or // LENGTHS [,flags // string; "o" (orient) or // "s" (scaled) [,strength]]]) // number
CORE |
drill out the foreground polygons that fall within the background template's shape, leaving only the core |
TUNNEL |
opposite of CORE; removes polygons that fall within the template's shape, leaving non-core data |
SLICE |
cut's through the foreground object, creating a visible incision along the template's edges |
STENCIL |
identical to SLICE, except you can assign a surface name to all polygons that fall within the template's shape |
The optional surface parameter is used when the STENCIL operation is specified.
status axisdrill(operation, // constant, CORE, TUNNEL, // SLICE or STENCIL axis // constant, X, Y or Z [,surface]) // string, surface name // (for STENCIL)
status soliddrill(operation // constant, CORE, TUNNEL, // SLICE or STENCIL [,surface]) // string, surface name // (for STENCIL)
UNION |
merge the volumes of each object into a single, new object; interior surfaces where the two object overlap will be removed |
SUBTRACT |
remove the volume of the background object(s) from the foreground object(s) |
INTERSECT |
create an object that is the area the two objects had in common |
ADD |
add background object(s) to the foreground object(s); intersection of polygons are sliced to form a common edge |
status boolean(operation) // constant, UNION, // SUBTRACT, INTERSECT // or ADD
status bevel(inset, // number; uniform amount // of displacement // along polygon plane shift) // number; displacement // amount // perpendicular to // polygon plane
The example script router.ls relies heavily on this command for its functionality. The following code snippet that illustrates the usage of this command was taken from that script:
s = string(-wide," ",wide," ",-wide," ",deep / 2); shapebevel(s);The prototype for this command appears as
status shapebevel(pattern) // string; pairs of // inset/shift pairs
status smoothshift(offset // number; shift offset [,max]) // number; maximum angle in // degrees
status flip(void)
status triple(void)In particular, you will want to triple() an object (especially if it contains 4-sided polygons) prior to subdividing it. The following code snippet illustrates this:
points = polycount(); if(points[5] or points[6]) // it has polygons with 4 or more sides triple() subdivide(METAFORM);
status freezecurves(void)
status alignpols(void)
status removepols(void)
status unifypols(void)
FLAT |
subdivide polygons, leaving the newly divided polygons in the same plane as the originals |
SMOOTH |
extrapolates where subdivided detail should be placed to maintain and enhance the curvature of the original form |
METAFORM |
smooths dramatically; locations which contain greater detail will have more detail in the smoothing process |
status subdivide(mode // constant; FLAT, SMOOTH // or METAFORM [,max]) // number; maximum angle to // consider (in // degrees)
status fracsubdivide(mode, // constant; FLAT, SMOOTH // or METAFORM fractal // number; fractal // displacement amount [,max]) // number; maximum angle to // consider (in // degrees)
SET the minor mode that follows, if any, will define points that are to be selected CLEAR the minor mode that follows, if any, will define points that are to be deselected One of these two major modes will always be the first parameter to selpoint(). They are the only non-optional parameters to the command, and can appear in the parameter list by themselves (i.e., selpoint(CLEAR) will deselect all currently-selected points).
The minor modes supported by selpoint() allow the script programmer to designate point selection in a number of different ways. The minor modes for selpoint() include:
Minor Mode | Arguments | Description |
VOLUME |
two vectors, indicating the low and high points of the bounding box | selects/clears points that fall within a specified bounding box. |
CONNECT |
none | selects points that are connected to points that are already selected. Only works with the SET major mode. |
NPEQ |
number, indicating the count of points that qualifying polygons should contain | selects/clears all points belonging to polygons that contain exactly the number of points specified by the argument. |
NPLT |
number, indicating the count of points that qualifying polygons should not exceed | selects/clears all points belonging to polygons that contain fewer than the number of points specified by the argument. |
NPGT |
number, indicating the count of points that qualifying polygons should exceed | selects/clears all points belonging to polygons that contain more than the number of points specified by the argument. |
POINTNDX |
number, representing the linear index of the point; array, containing a list of integer values that represent linear point indices; initialization block, containing integer values representing linear point indices. | selects/clears the point that exists in Modeler's internal list of points at the specified index |
POINTID |
point identifier, derived from some MeshDataEdit mode function; or an array or initialization block of point identifiers, as described in POINTNDX. | selects/clears all points identified by the provided point identifier(s) |
It is important to note that you need to set your script into USER mode using the selmode() command before selpoint() (and selpolygon()) will work properly.
Here, then, is the prototype for selpoint():
status selpoint(major // constant; SET or CLEAR [,minor, // constant; VOLUME, // CONNECT, NPEQ, // NPLT, NPGT or // POINTID params]) // varies; minor-mode // parameters // outlined previously
Minor Mode | Arguments | Description |
VOLEXCL |
two vectors, indicating the low and high points of the bounding box | selects/clears polygons whose points fall completely within the specified bounding box |
VOLINCL |
two vectors, indicating the low and high points of the bounding box | selects/clears polygons that have at least one point that falls within the specified bounding box |
CONNECT |
none | selects polygons that are connected to polygons that are already selected. Only works with the SET major mode. |
NVEQ |
number, indicating the count of vertices that qualifying polygons should contain | selects/clears all polygons that contain exactly the number of vertices specified by the argument. |
NVLT |
number, indicating the count of vertices that qualifying polygons should not exceed | selects/clears all polygons that contain fewer than the number of vertices specified by the argument. |
NVGT |
number, indicating the count of vertcies that qualifying polygons should exceed | selects/clears all polygons that contain more than the number of vertices specified by the argument. |
SURFACE |
string, indicating the name of the surface assigned to qualified polygons | selects/clears all polygons that have been assigned the specified surface name. |
FACE |
none | selects/clears all polygons that Modeler considers to be of type "face". |
CURVE |
none | selects/clears all polygons that Modeler considers to be of type "curve". |
NONPLANAR |
number, an optional numeric value that indicates the planar selection limit | selects/clears polygons who are less planar than the specified argument. if the optional argument is omitted, then the user's default planar limit will be used. |
POLYNDX |
number, representing the linear index of the polygon; array, containing a list of integer values that represent linear polygon indices; initialization block, containing integer values representing linear polygon indices. | selects/clears the polygon that exists in Modeler's internal list of polygons at the specified index |
POLYID |
polygon identifier, derived from some MeshDataEdit mode function; or an array or initialization block of polygon identifiers, as described in POLYNDX. | selects/clears all polygons identified by the provided polygon identifier(s) |
As with selpoint(), you must set your script session into USER mode using the selmode() command for selpolygon() to function properly.
status selpolygon(major // constant; SET or CLEAR [,minor, // constant; VOLEXCL, // VOLINCL, CONNECT, // NVEQ, NVLT, NVGT, // SURFACE, FACE, // CURVE, NONPLANAR // or POLYID params]) // varies; minor-mode // parameters // outlined previously
status selinvert(void)
status selhide(which) // constant; SELECTED or // UNSELECTED
status selunhide(void)
status setsurface(name) // string; new surface name
string getdefaultsurface(void)
status changesurface(name) // string; surface name to // which selected // polygons will // belong
// display all the current surface names var surface = nextsurface(); info(surface); while(true) { if((surface = nextsurface(surface)) == nil) break; info(surface); }The prototype:
result // string; surface name nextsurface([name]) // string; optional surface // name
status renamesurface(orig, // string; existing surface // name new) // string; new surface name
status createsurface(name) // string; new surface name
status copysurface(orig, // string; existing surface name new) // string; new surface name
result // integer; number of fonts // loaded fontcount(void)
result // integer; font index fontindex(name) // string; font name
result // string or nil; font name fontname(index) // integer; font index // value
var fontName = getfile("Select a Font"); if(fontName == nil) return; var findex = fontload(fontName); if(findex != nil) { maketext("LScript",findex); fontclear(findex); // release the font immediately ...The prototype:
result // integer; font index // or nil fontload(name) // string; font name with // optional path
status fontclear(index) // integer; font index // value
The name used to invoke another plugin should be identical to the name as that appears under your Custom menu button. The arguments you pass to a plugin depend upon how that plugin has been programmed. Most plugins will not accept parameters, not having been specifically designed to be invoked in this fashion.
status cmdseq(name // string; plugin name [,arguments]) // string; value varies by // plugin
All of getfile()'s parameters are optional. You can specify a title for the dialog box, a file name mask to be used, and even a default directory to use.
result // string or nil; file name getfile([title // string; dialog box title [,mask // string; file mask to use // (can include // wildcards) [,dir]]]) // string; directory path // in which to begin
The monitor system is basically a progress indicator. A progress indicator let's your user know that things are actually taking place, and that the computer has not locked-up for some reason. You initialize the monitor by telling it how many steps you need to take before you have completed your work. The monitor system uses this value to display a graphical progress bar so that the user knows how much more time will be required until completion.
You can optionally provide a message that will be displayed to the user in the monitor dialog box during display. Notice that the monitor window is actually a dialog. The user can press a Cancel button provided by the dialog box at anytime. This action is handled by the monstep() function (discussed next).
void moninit(steps // integer; number of steps // until completion [,message]) // string; message to be // displayed to user
monstep() will return a Boolean value. Most of the time, this value will be false. However, should the user press the Cancel button on the monitor window, this command will return true. When this takes place, your script should exit as gracefully as possible.
editbegin(); ... if(monstep()) { lyrsetfg(fg); lyrsetbg(bg); editend(ABORT); return; }And the prototype:
boolean monstep([step]) // integer; optional // advance amount
void monend(void)
reqbegin() is called to initiate a Modeler "requester." This requester is basically an input dialog box used to gather information and options from the user. It can also be used to impart information and messages (as static text).
Invoking reqbegin() will place you into requester mode. This mode must be active for other requester-related functions to be used , and must be terminated by a call to reqend(). You may terminate your script at any time during requester mode, and LScript will automatically issue a reqend() if you forget to do so.
reqbegin() takes a single argument, which is the title to be used for your requester dialog.
void reqbegin(title) // string; dialog box title
void reqend(void)
reqpost() will return a Boolean value (true or false) indicating whether or not the user chose to continue processing with the provided values. A value of true indicates that the user selected Ok, and that processing should commence. A false return is an indicator that your should gracefully terminate your script because the user has decided to Cancel.
result // boolean; true if user // selected "Ok" reqpost(void)
... name = "BillyBob"; age = 18; c1 = ctlstring("Your name?",name); c2 = ctlinteger("Your age?",age); ...ctlvector() accepts a rather flexible format in its parameters. You can provide a single vector data type, a single numeric value that will be used to populate all three fields, or you can provide three individual numeric values to be used to initialize the individual edit fields.
... length = .25; c1 = ctldistance("Length",length); // if selected default units are // kilometers, then this edit // field will initially be // (.25 * 1k) == 250 meters ...
ctlchoice() requires three parameters, and accepts an optional fourth. The first, as with all other control-creation functions, is the control title. The second is an integer value, used to specify the initial push button that will be selected when the panel is posted. The third is either an array reference containing the character strings that will be used as the button labels, or it can be an initialization block placed directly into the function call that houses the same data. Selection numbers begin at one (1).
booleans[1] = "Yes"; booleans[2] = "No"; choice = 2; // set "No" as initial selection c1 = ctlchoice("Use random height?",choice,booleans);The (optional) fourth parameter can be provided to indicate the orientation of the selection list. Selection lists can be organized with either vertical or horizontal grouping. This fourth parameter selects a specific orientation by specifying a Boolean true for vertical and false for horizontal. If omitted, horizontal orientation is used by default.
choice = 1; // set "No" as initial selection // create a vertical selection list c1 = ctlchoice("Quadrant?",choice,@"90","180","270"@,true);
ctltext() accepts a variable number of arguments, all of which should be text strings. As with all control-creation functions, the first text string provided is always treated as the control title.
ctltext("WARNING", // <-- first arg is control title "This operation could take a long time,", "and create very many points if Level is high");Like all other control functions, ctltext() will return the control handle of the static text control. However, because the control does not change, this handle is of little value. It could be used by the setvalue() function to alter the text before re-posting the dialog box.
As with ctlvector(), ctlcolor() also accepts a combination of parameters and types. You can provide a single vector data type, a single integer value that will be used to populate all three fields, or you can provide three individual integer values to be used to initialize the individual edit fields.
Both functions take the control title from the first parameter provided. ctlsurface() assumes that the second string parameter is the name of a surface to be used to initialize the surface control. cltfont() requires an integer value as its second parameter that indicates the index of a currently-loaded font that is to be used as the control's initial value.
result // varies; data value // contained in field getvalue(handle) // integer; control handle
setvalue() allows you to modify the value of an existing requester control. It accepts a handle to the control to be changed, and a variable or constant value to used as the new value. Please examine the lightswa.ls script, provided on your LightWave distribution, for an example of this practice.
void setvalue(handle, // integer; control handle value) // data type; new value for // input field
Using listadd(), you can establish the name that will appear under the User menu, the server to be used to process the selection (in the case of LScripts, the server name would be "LScript"), and the file name (with optional path) of the file that represents the entry.
listremove() can be used to remove an entry from the User menu. Only the name of the User menu entry needs to be provided.
When server-based entries are placed in the User menu in this fashion, Modeler maintains them separately from its own internal commands (i.e., Add Plugin) and plugins. To accomplish this, your server-based entries are stored in a specific file that it will automatically reload each time you start Modeler. However, for Modeler to be aware of these commands, you must save them during the session in which you╞ve added them. To save your new entries for later loading, use the Configure List command under the User menu. See your Modeler documentation for more information.
status listadd(title, // string; title of entry // under User menu server, // string; name of server // to be used to // process entry file) // string; disk file to // which this entry // points status listremove(title) // string; title of entry // to be removed
In GLOBAL selection mode, Modeler-specific operations will occur on all points/polygons in the active foreground layer(s), regardless of what user-selected data exists. USER selection mode will cause Modeler-specific commands to operate only on those points and polygons that have been explicitly selected by the user (or implicitly on all points and polygons if no user-selected data exists).
The selection commands selpoint() and selpolygon() will not function unless the USER selection mode is active.
void selmode(mode) // constant; GLOBAL or USER
editbegin() places your LScript into MeshDataEdit mode. When you enter this mode, certain magical things take place:
1. |
CommandSequence (CS/1.0) commands and functions are now illegal. You may not invoke these types of procedures until you leave MeshDataEdit mode using editend(). |
2. |
Two new, automatic LScript arrays become available. The first, called points[], contain the point ids of all the currently-selected object points. The second, called polygons[], contains the polygon ids of all the currently-selected object polygons. |
In the case of the automatic arrays points[] and polygons[], should you have declared arrays or variables with the same names within the scope of the MeshDataEdit mode, they will be hidden. They will become visible once again when you have terminated MeshDataEdit mode using editend().
editbegin() will return the count of points that are currently selected. This count will be equal to the size of the points[] automatic array.
result // integer; count of // selected points editbegin(void)
During MeshDataEdit operations, Modeler will "queue up" all modifications that are made to the object data. Modifications will not be applied to your object until you issue the editend() command. By default, if you provide no parameters to editend(), your changes will be applied to your object and processing will continue. However, you can provide a parameter to editend() that will cause your accumulated changes to be discarded, and leave your object unchanged. This parameter can be a constant, ABORT, or any non-zero value to indicate your wish to discard all changes.
void editend([status]) // constant; ABORT
boundingbox() can be called at anytime, regardless of mode. However, if boundingbox() is used during MeshDataEdit, layers cannot be specified, and any that are will be ignored.
If there are no point/polygon data in the specified layer(s), then nil will be returned for each vector.
result // vector[2]; lower and // upper vectors of // bounding box or // nil[2] if no data // exists boundingbox([layers]) // integer or integer[]; an // integer array of // layer numbers, or // layer numbers // separated by commas
pointcount() can be called at any time.
result // integer; selected-point // count pointcount(void)
[1] | total number of selected polygons |
[2] |
total number of selected polygons that contain only one (1) point. |
[3] |
total number of selected polygons that contain only two (2) points |
[4] |
total number of selected polygons that contain only three (3) points |
[5] |
total number of selected polygons that contain only four (4) points |
[6] |
total number of selected polygons that contain more than four (4) points |
This data can be used to examine the state of an object. For instance, before METAFORM'ing an object, you must convert all four-sided polygons into triangles. You could accomplish this with the following code snippet:
var totalpoints[6]; totalpoints = polycount(); if(totalpoints[5] || totalpoints[6]) triple(); subdivide(METAFORM);polycount() can be called at anytime, not necessarily only from within a MeshDataEdit mode.
result // integer[6]; polygon // counts of varying // point counts polycount(void)
result // point id; the identifier // for the new vector addpoint(location) // integer[3], vector or // number; the // location of the new // point
The new polygon can optionally be assigned to a surface name. If the surface parameter is omitted, then the new polygon will belong to the default surface identifier. If the specified surface name does not exist, it will be created.
The new polygon identifier is returned upon success, or nil if there was a failure.
result // polygon id or nil; the // identifier of the // new polygon addpolygon(points // point id[] or point id; // point identifiers // of new polygon [,surface]) // string; surface name to // which polygon // should be assigned
The gears.ls sample script, provided on your distribution diskette, is a good example of using both addpolygon() and addcurve().
result // polygon id or nil; the // identifier of the // new curve addcurve(points // point id[] or point id; // point identifiers // of new curve [,surface]) // string; surface name to // which curve // should be assigned
result // polygon id; new polygon // identifier or nil addquad(points) // point ids[4] or 4 // individual point // ids; points to use // in constructing // quadrangle
result // polygon id; new polygon // identifier or nil addtriangle(points) // point ids[3] or 3 // individual point // ids; points to use // in constructing // triangle
Because not all polygons in an object will have the same number of points, the point count of a polygon will likely vary from polygon to polygon. To help you determine the number of points a polygon contains you can use the polypointcount() function (discussed next) to allocate an array of the appropriate size to hold the return value of polyinfo().
result // array[]; variable // sized array whose // first element is // surface name, // remaining elements // are point ids polyinfo(polygon) // polygon id; the polygon // identifier for // which you need // information
... var pcount = polypointcount(polygons[x]); var ppoints[pcount + 1]; // account for surface name [1] ppoints = polyinfo(polygons[x]); ...The prototype:
result // integer; point count polypointcount(polygon) // polygon id; the polygon // in question
result // vector; location of // point pointinfo(point) // point id; identifier of // point in which you // are interested
result // vector; surface normal // of polygon or nil polynormal(polygon) // polygon id; identifier // of polygon
status rempoint(point) // point id; the point to // be removed status rempoly(polygon) // polygon id; the polygon // to be removed
status pointmove(point, // point id; the point to // be moved location) // integer[3], vector or // number; the new // location of the // point
status polysurface(polygon, // polygon id; the polygon // to change surface) // string; surface name to // which polygon is // now assigned
status polypoints(polygon, // polygon id; polygon // to change points // point ids[]; new points // for polygon